//-----------------------------------------------------------------------
// <copyright file="DataManager.h" company="Microsoft">
//      Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// Module:
//      DataManager.h
//
// Description:
//      DataManager Class
//
//-----------------------------------------------------------------------
#pragma once

class CDataManager
{
public:
    CDataManager(CWssBasicDDI* pDDI);
    ~CDataManager();

    HRESULT Initialize();

    // AddApplication adds (or updates) an application which creates an ApplicationNode (if one doesn't exist), but doesn't add application data to the node
    // This will also need to get the sort order to add the nodes in the proper order.
    HRESULT AddApplication(GUID guidApplicationId,
                           LPCWSTR wszTitle,
                           const BYTE* pIcon,
                           size_t cbIcon,
                           const BYTE* pMiniIcon,
                           size_t cbMiniIcon
                           );

    HRESULT UpdateApplicationNode(GUID guidApplicationId, LPCWSTR wszBody);

    HRESULT DeleteApplication(GUID guidApplicationId); // This deletes an application, its related ApplicationNode,
                                                       // and all associated notifications for the application
    HRESULT DeleteAllApplications(void); // This calls a loop of DeleteApplications.
                                         // It's also called upon SetCurrentUser user switch

    HRESULT GetApplications(__deref_out_ecount(*pcAppIds) APPLICATION_ID** ppAppIds, __out DWORD* pcAppIds);

    // This changes the sort order for the applications. Note, this list can contain ApplicationId's which don't
    // correspond to existing ApplicationNodes. They will be stored here for later use.
    HRESULT ChangeSortOrder(__in_ecount(cApps) const APPLICATION_ID* pApps, const DWORD cApps);

    HRESULT AddNotification(GUID guidApplicationId,
                            unsigned long ulNotificationId,
                            LPCWSTR wszTitle,
                            LPCWSTR wszBody,
                            const BYTE* pIcon,
                            size_t cbIcon,
                            FILETIME ftExpirationTime);

    HRESULT DeleteNotification(GUID guidApplicationId,
                               unsigned long ulNotificationId);
    

    HRESULT HandleDeviceEvent(CDevice::DeviceEvent DeviceEvent); // Such as a Next or Previous button
                                                        // This determines what the event is, and performs the proper action which might include
                                                        // updating the display on the device

    HRESULT TimerMaintenance(void); // The timer thread calls this once every second.
                                    // This call will handle expired notifications, and auto-change the current page on the
                                    // device (defaults to every 5 seconds). This time will be set from the IHV property page in the CPL
                                    // Note, if the user presses Next, this resets the auto-change timer.

    //
    // Contents
    //
    HRESULT AddContent(
                    REFAPPLICATION_ID rAppId,
                    CONTENT_ID contentId,
                    const unsigned char* pData,
                    const DWORD cbData);
    
    HRESULT RemoveContent(
                    REFAPPLICATION_ID rAppId,
                    CONTENT_ID contentId);

    HRESULT RemoveAllContent(REFAPPLICATION_ID rAppId);
    
    CONTENT_ID GetCurrentContentId() const { return m_CurrentContentId; }
    void SetCurrentContentId(CONTENT_ID contentId);

    //
    // Context Menu
    //
    VOID SetContextMenu(CONTENT_ID contextMenuId, UINT32 menuItemId = 0);
    VOID ClearContextMenu();
    BOOL IsContextMenuActive() { return m_bContextMenu; }
    CONTENT_ID GetContextMenuId() { return m_ContextMenuId; }
    UINT32 GetContextMenuPreviousItemId() { return m_ContextMenuPreviousItemId; }

    //
    // Application Accessor
    //
    size_t GetApplicationCount() { return m_ApplicationNodes.size(); }
    size_t GetCurrentApplicationIndex() { return m_nApplicationMenuIndex; }
    CNodeApplication *GetApplicationByIndex(size_t index) { return m_ApplicationNodes[index]; }
    CNodeApplication *GetApplicationById(REFAPPLICATION_ID rAppId);
    CNodeApplication* GetCurrentApplication();
    
    //
    // Back ContentId Stack
    //
    HRESULT PushCurrentContentId();
    VOID EmptyBackContentIdStack();
    
    //
    // Back and Home
    //
    VOID HandleBackButton();
    VOID GotoHome();

    //
    // Renderer
    //
    CRenderer *GetRenderer() { return &m_renderer; }

    //
    // BasicDDI
    //
    CWssBasicDDI *GetDDI() { return m_pDDI; }

    //
    // Handle internal commands
    //
    HRESULT HandleInternalCommand(CONTENT_ID contentId, CONTENT_ID targetId, LONG nIndex);
    
#ifdef _ASSIGNED_USER_MODEL
    //
    // Assinged User Model
    //
    HRESULT AddUser(const SID *pUserSID);
    HRESULT RemoveUser(const SID *pUserSID);
#endif

private:
    HRESULT DeleteAllNotificationsForAnApplication(GUID guidApplicationId, BOOL *pbRender);
    HRESULT DeleteAllNotifications(void);
    HRESULT RenderProperPage(IStream *pStream, DWORD *pdwRenderFlags);
    HRESULT RenderAndSendDataToDevice();
    HRESULT _InitializeHomeScreenContextMenuContent();
#ifdef _ASSIGNED_USER_MODEL
    HRESULT _CreateSelectUserContent(BOOL bDefAttr);
#endif
    HRESULT _CreateSelectThemeMenuContent();
    VOID _DeleteAllApplications();

    // This method returns a valid application node index (one with wszBody != NULL),
    // starting with the current node and moving forward,
    // or it returns INVALID_APPLICATION_NODE_INDEX if there isn't one
    size_t ForwardFindValidApplicationNodeIndex(void);

    CWssBasicDDI* m_pDDI;
    
    NODENOTIFICATIONVECTOR m_NotificationNodes;
    NODEAPPLICATIONVECTOR m_ApplicationNodes;
    size_t m_nApplicationMenuIndex;
    CNodeApplication* m_pCurrentApplication;

    CONTENT_ID m_CurrentContentId;
    stack<CONTENT_ID> m_BackContentIdStack;

    BOOL m_bContextMenu;
    CONTENT_ID m_ContextMenuId;
    UINT32 m_ContextMenuPreviousItemId;
    
    CRenderer m_renderer;
    CTimer m_timer;

    CRITICAL_SECTION m_CriticalSection;

    // default context menu content which has only "Back" and "Home"
    CContent m_DefaultContextMenuContent;
    CContent m_HomeScreenContextMenuContent;    // context menu for home screen
    
    IStream *m_pImageSink;


#ifdef _ASSIGNED_USER_MODEL
    vector<CUserInfo *> m_Users;
#endif
    CNodeApplication m_BuiltinApplication;  // internal special application for select user, configure, select theme, etc

    UINT32 m_ThemeIndex;
};

